<template>
  <div class="filelist of rel">
    <div class="loading absfill c1 fsm" flex="main:center cross:center" v-if="loading">
      <i class="iconfont icon-loading f32"></i>&nbsp;<span>压缩图片中,请稍等</span>
    </div>
    <div class="item">
      <label class="fileadd inner" flex="main:center cross:center">
        <i class="iconfont icon-jiahao f64 gray"></i>
        <input type="file" style="display: none" @change="_onChange" ref="fileinput" v-if="reset"
               accept="image/*"/>
      </label>
    </div>
    <div class="item" v-for="(i,index) in images" :key="index">
      <div class="inner red-bg" :style="{'background-image': `url(${i.src})`}" :class="{'info': i.state == null}">
        <div class="uploading absfill" v-if="i.state == null" :style="{'transform': `scaleX(${1-i.progress})`}"></div>
        <div v-if="i.state == false" class="error absfill" flex="main:center cross:center"><i
          class="iconfont icon-error"></i></div>
        <p class="del" flex="main:center cross:center">
          <i class="iconfont icon-shanchu" @click="onDel(index)"></i>&nbsp;删除
        </p>
      </div>
    </div>
  </div>
</template>
<script>
  import urljoin from 'url-join'
  import ImageCompressor from 'image-compressor.js';
  const MAX_SIZE = 1048576
  export default {
    props: {
      url: {
        type: String,
        default: urljoin(baseURL, 'wx/upload/img')
      },
      // 文件大小限制 字节
      fileSizeLimit: Number,
      // 文件个数限制
      fileNumLimit: Number
    },
    data() {
      return {
        images: [],
        reset: true,
        loading: false
      }
    },
    computed: {
      names() {
        return this.images.map(x => x.file.name)
      }
    },
    methods: {
      // 选择文件
      async _onChange() {
        let files = Array.from(this.$refs.fileinput.files)
        this._fileNumLimit(files) // 删除超出文件
        files = files.filter(x => this._noRepeat(x) && this._fileSizeLimit(x))
        files = files.map(file => new Promise((resolve, reject) => {
          console.log('源文件', file.name, Number(file.size / 1024 / 1024).toFixed(2))
          const quality = MAX_SIZE / file.size
          if (quality >= 1) {
            resolve(file)
            return
          }
          new ImageCompressor(file, {
            quality,
            success: result => {
              resolve(result)
            },
            error: error => reject(error),
          })
        }))
        this.loading = true
        files = await Promise.all(files)
        this.loading = false
        this._preview(files)
        this._resizeInput()
      },
      onDel(index) {
        this.images.splice(index, 1)
      },
      // 重置 input 文件选项
      async _resizeInput() {
        this.reset = false
        await this.$nextTick()
        this.reset = true
      },
      // 图片预览
      _preview(files) {
        let count = 0
        files.forEach(file => {
          const reader = new FileReader()
          reader.readAsDataURL(file)
          reader.onload = async result => {
            const image = {
              file: file,
              src: result.target.result,
              progress: 0,
              state: null
            }
            this.images.push(image)
            await this.$nextTick()
            new Upload(this.url, image).start(() => this.$emit('input', this.images.map(({cloud}) => cloud))) // 上传成功，并触发返回 “云图片地址” 事件
          }
        })
      },

      // 上传文件
      _upload() {

      },
      // 文件去重
      _noRepeat({name}) {
        return !this.names.includes(name)
      },
      // 文件超出大小过滤
      _fileSizeLimit({size}) {
        if (this.fileSizeLimit) {
          const result = size < this.fileSizeLimit
          result || this.$emit('fileSizeLimit', this.$data)
          return result
        }
        return true
      },

      // 文件数量限制
      _fileNumLimit(files) {
        if (this.fileNumLimit > 0) {
          this.$emit('fileSizeLimit', this.$data)
          return files.slice(0, Math.max(this.fileNumLimit - this.images.length, 0))
        }
        return files
      }
    },
    components: {}
  }

  class Upload {
    constructor(url, image) {
      this.image = image
      const xhr = this.xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
      xhr.open("post", url, true); //post方式，url为服务器请求地址，true 该参数规定请求是否异步处理。
      xhr.onload = this._success.bind(this)
      xhr.onerror = this._error.bind(this)
      xhr.upload.onprogress = this._progress.bind(this)
      xhr.upload.onloadstart = this._loadstart.bind(this)
    }

    start(callback) {
      this.callback = callback
      const form = new FormData(); // FormData 对象
      form.append("file", this.image.file, this.image.file.name)
      console.log('压缩后', this.image.file.name, Number(this.image.file.size / 1024 / 1024).toFixed(2))
      this.xhr.send(form); //开始上传，发送form数据
    }

    _success({target}) {
      var data = JSON.parse(target.responseText)
      if (data.code == 200) {
        this.image.progress = 1
        this.image.state = true
        this.image.cloud = data.msg
        this.callback(data.msg)
      }
    }

    _error() {
      this.image.state = false
    }

    _progress({total, loaded, lengthComputable}) {
      // event.total是需要传输的总字节，event.loaded是已经传输的字节。如果event.lengthComputable不为真，则event.total等于0
      if (lengthComputable) {
        this.image.progress = loaded / total
      }
    }

    _loadstart() {
    }
  }
</script>
<style type="text/scss" lang="scss" scoped>
  .fileadd {
    border: 1px dashed #dcdcdc;
  }

  // 图片上列表
  .filelist {
    $space: 10px; // 图片间距
    $rows: 4; // 一行多少个
    margin-top: -$space;
    margin-left: -$space;
    .item {
      position: relative;
      width: #{100% / $rows};
      float: left;
      &:before {
        display: inline-block;
        content: '';
        padding-top: 100%;
      }
      .inner {
        position: absolute;
        top: $space;
        left: $space;
        right: 0;
        bottom: 0;
        background-position: center;
        background-size: cover;
      }
    }
  }

  ing {
    opacity: .3;
  }

  .error {
    background-color: rgba(255, 255, 255, .8);
    i {
      font-size: 32px;
      color: #f5222d;
    }
  }

  .del {
    position: absolute;
    font-size: 12px;
    bottom: 0;
    left: 0;
    right: 0;
    height: 18px;
    color: #f5222d;
    z-index: 1;
    background-color: rgba(255, 255, 255, .8);
  }

  .loading {
    background-color: rgba(255, 255, 255, .8);
    z-index: 1;
    i {
      display: inline-block;
      animation: loading-rotate 2s linear infinite;
    }
  }

  .uploading {
    transition: transform 0.3s;
    transform-origin: 0 50%;
    background-color: rgba(255, 255, 255, .8);
  }

  @keyframes loading-rotate {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }
</style>
